#ifndef SLICEFRACTIONCOLLECTION_H
#define SLICEFRACTIONCOLLECTION_H

#ifndef CORE_H
# include "..\..\..\Core\System\Core.h"
#endif
#include "..\..\..\Core\System\TreeSet.h"
#include "Limits.h"
#include "SliceFraction.hpp"

namespace System { namespace Scheduler {

	typedef struct { ulong key; SliceFraction* value; } SliceFractionPair;

	class SliceFractionCollection
	{
	private:
		TreeSet<SliceFractionPair> _set;
		fallocContext* _fallocCtx;

		__device__ bool TryGetValue(ulong key, SliceFraction** value)
		{
			SliceFractionPair pair;
			pair.key = key;
			Node<SliceFractionPair>* node = _set.FindNode(pair);
			if (node == nullptr)
				return false;
			*value = node->item.value;
			return true;
		}

		__device__ void Add(ulong key, SliceFraction* value)
		{
			SliceFractionPair pair;
			pair.key = key; pair.value = value;
			_set.Add(pair);
		}

	public:
		__device__ void xtor(fallocContext* fallocCtx)
		{
			trace(SliceFractionCollection, "xtor");
			_fallocCtx = fallocCtx;
			_set.xtor(0, fallocCtx);
		}

		__device__ void Schedule(Element* element, ulong fraction)
        {
			trace(SliceFractionCollection, "Schedule %d", TimePrec__DecodeTime(fraction));
            SliceFraction* fractionAsObject;
            if (!TryGetValue(fraction, &fractionAsObject))
			{
				fractionAsObject = falloc<SliceFraction>(_fallocCtx);
				if (!fractionAsObject)
					thrownew(OutOfMemoryExcepton);
				fractionAsObject->xtor(_fallocCtx);
                Add(fraction, fractionAsObject);
			}
            fractionAsObject->Elements.Add(element, 0);
        }

	};

}}

#endif // SLICEFRACTIONCOLLECTION_H

